package net.chery.exec;

import com.huawei.bigdata.security.LoginUtil;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author gai
 * 连接大数据hive数据库
 */
@Slf4j
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "other.datasource."+ HiveExec.KEY)
public class HiveExec extends BaseExec {
    public static final String KEY="hive";
    private String home;
    private String keytab;

    @Scheduled(fixedDelay = 10*60*1000)
    public void closeDatasource(){
        if(!dataSource.isClosed()&&System.currentTimeMillis()-initTime>20*60*1000&&!isActive()){
            dataSource.close();
            log.warn("hive datasource has be closed");
        }
    }

    @Override
    protected void init() throws Exception{
        System.setProperty("hadoop.home.dir",home);
        Configuration conf = new Configuration();
        String keytabFile=keytab+"user.keytab";
        conf.addResource(new Path(keytab+"core-site.xml"));
        conf.addResource(new Path(keytab+"hive-site.xml"));
        LoginUtil.setJaasConf("Client", getUsername(), keytabFile);
        LoginUtil.login(getUsername(), keytabFile,
                keytab+"krb5.conf",
                conf);
        super.init();
    }

    public Map<String, List<String>> getTables(){
        Map<String,List<String>> res=new HashMap<>(16);
        exec("SHOW DATABASES",(rs)->{
            try {
                String database=rs.getString(1);
                List<String> tables=new ArrayList<>();
                try (Connection connection=getConnection();
                     PreparedStatement statement=connection.prepareStatement("use "+database)
                ){
                    statement.execute();
                    ResultSet t =connection.prepareStatement("show tables").executeQuery();
                    while (t.next()){
                        tables.add(t.getString(1));
                    }
                }
                res.put(database,tables);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        });
        return res;
    }

    public List<List<String>> desc(String tableName){
        if(!StringUtils.hasLength(tableName)){
            return new ArrayList<>();
        }
        List<List<String>> res=new ArrayList<>();
        exec("DESC "+tableName,(rs)-> {
            try {
                int x = rs.getMetaData().getColumnCount();
                while (rs.next()) {
                    List<String> c = new ArrayList<>(x);
                    for (int i = 1; i <= x; i++) {
                        c.add(rs.getString(i));
                    }
                    res.add(c);
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        });
        return res;
    }
}
